
/**
 * @fileoverview Default renderer for {@link mp.ui.Pane}s.
 *
 * @author alert@google.com
 */

goog.provide('mp.ui.PaneRenderer');

goog.require('goog.dom.a11y.Role');
goog.require('goog.dom.classes');
goog.require('goog.object');
goog.require('goog.ui.ContainerRenderer');



/**
 * Default renderer for {@link mp.ui.Pane}s, based on the {@code TabPane}
 * code.  The pane's DOM structure is determined by its orientation and
 * view.
 * @constructor
 * @extends {goog.ui.ContainerRenderer}
 */
mp.ui.PaneRenderer = function () {
    goog.ui.ContainerRenderer.call(this);
};
goog.inherits(mp.ui.PaneRenderer, goog.ui.ContainerRenderer);
goog.addSingletonGetter(mp.ui.PaneRenderer);


/**
 * Default CSS class to be applied to the root element of components rendered
 * by this renderer.
 * @type {string}
 */
mp.ui.PaneRenderer.CSS_CLASS = goog.getCssName('mp-pane');


/**
 * Returns the CSS class name to be applied to the root element of all panes
 * rendered or decorated using this renderer.
 * @return {string} Renderer-specific CSS class name.
 * @override
 */
mp.ui.PaneRenderer.prototype.getCssClass = function() {
  return mp.ui.PaneRenderer.CSS_CLASS;
};


/**
 * Returns the ARIA role to be applied to the pane element.
 * See http://wiki/Main/ARIA for more info.
 * @return {goog.dom.a11y.Role} ARIA role.
 * @override
 */
mp.ui.PaneRenderer.prototype.getAriaRole = function() {
  return goog.dom.a11y.Role.GRID;
};

/**
 * 
 * @param {mp.ui.Pane} pane Pane to update.
 * @param {mp.ui.Pane.View} view Pane view.
 * @protected
 */
mp.ui.PaneRenderer.prototype.setView = function (pane, view) {
    var viewClassName = goog.getCssName(this.getCssClass(), view);
    var oldViewClassName = goog.getCssName(this.getCssClass(), pane.getView());

    var element = (/** @type {Element} */
      pane.getElement ? pane.getElement() : pane);

    if (element) {
        goog.dom.classes.addRemove(element, oldViewClassName, viewClassName);
    }
};

/**
 * Sets the pane's state based on the given CSS class name, encountered
 * during decoration.  Overrides the superclass implementation by recognizing
 * class names representing pane orientation and view.
 * @param {goog.ui.Container} pane Pane to configure.
 * @param {string} className CSS class name.
 * @param {string} baseClass Base class name used as the root of state-specific
 *     class names (typically the renderer's own class name).
 * @protected
 * @override
 */
mp.ui.PaneRenderer.prototype.setStateFromClassName = function(pane,
    className, baseClass) {
  // Create the class-to-location lookup table on first access.
  if (!this.viewByClass_) {
    this.createViewByClassMap_();
  }

  // If the class name corresponds to a view, update the pane's view;
  // otherwise let the superclass handle it.
  var view = this.viewByClass_[className];
  if (view) {
    pane.setView(view);
  } else {
    mp.ui.PaneRenderer.superClass_.setStateFromClassName.call(this, pane,
        className, baseClass);
  }
};


/**
 * Returns all CSS class names applicable to the pane, based on its state.
 * Overrides the superclass implementation by appending the view-specific
 * class name to the list.
 * @param {goog.ui.Container} pane Pane whose CSS classes are to be
 *     returned.
 * @return {Array.<string>} Array of CSS class names applicable to the pane.
 * @override
 */
mp.ui.PaneRenderer.prototype.getClassNames = function(pane) {
  var classNames = mp.ui.PaneRenderer.superClass_.getClassNames.call(this,
      pane);

  // Create the view-to-class lookup table on first access.
  if (!this.classByView_) {
    this.createClassByViewMap_();
  }

  // Apped the class name corresponding to the pane's view to the list.
  classNames.push(this.classByView_[pane.getView()]);
  return classNames;
};


/**
 * Creates the view-to-class lookup table.
 * @private
 */
mp.ui.PaneRenderer.prototype.createClassByViewMap_ = function() {
  var baseClass = this.getCssClass();

  /**
   * Map of views to view-specific structural class names,
   * precomputed and cached on first use to minimize object allocations
   * and string concatenation.
   * @type {Object}
   * @private
   */
  this.classByView_ = goog.object.create(
      mp.ui.Pane.View.TILE, goog.getCssName(baseClass, 'tile'),
      mp.ui.Pane.View.LIST, goog.getCssName(baseClass, 'list'),
      mp.ui.Pane.View.GRID, goog.getCssName(baseClass, 'grid'));
};


/**
 * Creates the class-to-view lookup table, used during decoration.
 * @private
 */
mp.ui.PaneRenderer.prototype.createViewByClassMap_ = function() {
  // We need the classByView_ map so we can transpose it.
  if (!this.classByView_) {
    this.createClassByViewMap_();
  }

  /**
   * Map of view-specific structural class names to views, used during
   * element decoration.  Precomputed and cached on first use to minimize object
   * allocations and string concatenation.
   * @type {Object}
   * @private
   */
  this.viewByClass_ = goog.object.transpose(this.classByView_);
};
